@file:Suppress("unused")

package com.lalifa.extension

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.util.Base64
import android.util.DisplayMetrics
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.drake.logcat.LogCat
import com.drake.net.utils.scopeDialog
import com.drake.tooltip.dialog.BubbleDialog
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.XXPermissions
import com.lalifa.base.R
import com.lalifa.data.CityJsonBean
import com.lalifa.data.LoadCityBean
import com.lalifa.utils.SoftKeyBroadManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import per.goweii.layer.core.anim.AnimStyle
import per.goweii.layer.core.ktx.onClickToDismiss
import per.goweii.layer.core.ktx.onInitialize
import per.goweii.layer.dialog.DialogLayer
import per.goweii.layer.dialog.ktx.animStyle
import per.goweii.layer.dialog.ktx.backgroundDimDefault
import per.goweii.layer.dialog.ktx.cancelableOnTouchOutside
import per.goweii.layer.dialog.ktx.contentView
import per.goweii.layer.dialog.ktx.gravity
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Date
import java.util.regex.Pattern


/**
 * Activity extensions
 *
 * @author Classic
 * @version v1.0, 2019-05-20 15:48
 */
inline fun <reified T : Activity> Context.start(bunfle: Intent.() -> Unit = {}) {
    val starter = Intent(this, T::class.java)
    bunfle.invoke(starter)
    startActivity(starter)
}

fun Activity.start(cls: Class<out Activity>) {
    startActivity(Intent(this, cls))
}

fun Activity.start(cls: Class<out Activity>, intent: Intent.() -> Unit) {
    val intent1 = Intent(this, cls)
    intent(intent1)
    startActivity(intent1)
}

fun Activity.startCode(cls: Class<out Activity>, intent: (Intent.() -> Unit) = {}) {
    startActivityForResult(Intent(this, cls).apply(intent), 200)
}
fun Activity.startCode(
    cls: Class<out Activity>,
    code: Int = 200,
    intent: (Intent.() -> Unit) = {}
) {
    startActivityForResult(Intent(this, cls).apply(intent), code)
}
fun Activity.finish(code: Int, intent: (Intent.() -> Unit) = {}) {
    setResult(code, Intent().apply(intent))
    finish()
}

fun Activity.getIntentString(name: String): String {
    val stringExtra = intent.getStringExtra(name)
    return if (stringExtra.isNullOrEmpty()) {
        ""
    } else stringExtra
}

fun Activity.getIntentDouble(name: String, defaultValue: Double = 0.00): Double {
    return intent.getDoubleExtra(name, defaultValue)
}

fun Activity.getIntentBoolean(name: String, defaultValue: Boolean = false): Boolean {
    return intent.getBooleanExtra(name, defaultValue)
}

fun Activity.getIntentInt(name: String, defaultValue: Int = -1): Int {
    return intent.getIntExtra(name, defaultValue)
}

fun Activity.getIntentLong(name: String, defaultValue: Long = 0L): Long {
    return intent.getLongExtra(name, defaultValue)
}

fun <T> Activity.getIntentSerializable(name: String): T? {
    return intent.getSerializableExtra(name)?.let { it as T }
}

fun getNow(): Long {
    return System.currentTimeMillis()
}

/**
 * 显示软键盘
 */
fun Activity.showKeyboard(view: View?) {
    view?.requestFocus()
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.showSoftInput(view, 0)
}

/**
 * 关闭软键盘
 * @receiver Activity
 * @param view View?
 */
fun Activity.hideKeyboard(view: View?) {
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(view?.windowToken, 0)
    // imm.hideSoftInputFromWindow(view?.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

/**
 * 屏幕宽
 * @receiver Activity
 * @return Int
 */
fun Activity.screenWidth(): Int {
    val metrics = DisplayMetrics()
    windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.widthPixels
}

/**
 * 屏幕高
 * @receiver Activity
 * @return Int
 */
fun Activity.screenHeight(): Int {
    val metrics = DisplayMetrics()
    windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.heightPixels
}

fun Activity.fullScreen() {
    window.setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN
    )
}

/**
 * 状态栏透明
 * @receiver Activity
 */
fun Activity.makeStatusBarTransparent() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.apply {
            clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                decorView.systemUiVisibility =
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            } else {
                decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            }
            statusBarColor = Color.TRANSPARENT
        }
    }
}

fun Activity.isDestroy() = isFinishing || isDestroyed


val Activity.isInputOpen: Boolean
    get() = SoftKeyBroadManager((findViewById<ViewGroup>(R.id.content)).getChildAt(0)).isSoftKeyboardOpened

/**
 * 选择音乐文件
 * @receiver Activity
 * @param code Int
 */
fun Activity.startMusic(code: Int) {
    startActivityForResult(Intent(Intent.ACTION_GET_CONTENT).also {
        it.type = "audio/mpeg"//音频文件
        it.addCategory(Intent.CATEGORY_OPENABLE)
    }, code)
}

fun Activity.stringToBitmap(string: String): Bitmap? {
    var bitmap: Bitmap? = null
    try {
        val bitmapArray: ByteArray =
            Base64.decode(string.split(",").toTypedArray()[1], Base64.DEFAULT)
        bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return bitmap
}


private fun getTime(date: Date): String {
    val format = SimpleDateFormat("yyyy-MM-dd")
    return format.format(date)
}

/**
 * 获取asset目录指定文件的内容
 * @receiver Activity
 * @param fileName String
 * @return String
 */
fun Activity.getAsset(fileName: String): String {
    try {
        assets?.apply {
            assets.list("")?.forEach {
                if (it.equals(fileName)) {
                    val stringBuilder = StringBuilder()
                    val buffer = BufferedReader(InputStreamReader(assets.open(fileName)))
                    buffer.readLines().forEach {
                        stringBuilder.append(it)
                    }
                    return stringBuilder.toString()
                }
            }
        }
    } catch (e: Exception) {
        LogCat.e(e)
    }
    return ""
}

/**
 * 扩展方法
 * 倒计时的实现
 */
fun AppCompatActivity.countDown(
    time: Int = 60,
    start: (scop: CoroutineScope) -> Unit,
    next: (time: String) -> Unit,
    end: () -> Unit
) {
    lifecycleScope
    lifecycleScope.launch {
        // 在这个范围内启动的协程会在Lifecycle被销毁的时候自动取消
        flow {
            (time downTo 0).forEach {
                delay(1000)
                emit(it)
            }
        }.onStart {
            // 倒计时开始 ，在这里可以让Button 禁止点击状态
            start(this@launch)
        }.onCompletion {
            // 倒计时结束 ，在这里可以让Button 恢复点击状态
            end()
        }.catch {
            //错误
            Log.e("", it.message ?: "Unkown Error")
        }.collect {
            // 在这里 更新值来显示到UI
            next(it.toString())
        }
    }
}

fun AppCompatActivity.blocking() {
//    runBlocking {
//        val timer = TimerJob(5000L, 1000L)
//
//        timer.start(
//            onTick = { elapsedTime ->
//                println("Elapsed Time: $elapsedTime ms")
//            },
//            onFinish = {
//                println("Timer Finished!")
//            }
//        )
//
//        // 模拟计时器运行 3 秒后手动关闭计时器
//        delay(3000L)
//    }
}

//"yyyy-MM-dd HH:mm:ss"
fun Activity.dateStringToTimestamp(dateString: String, format: String): Long {
    val format = SimpleDateFormat(format)
    val date: Date = format.parse(dateString)
    return date.time
}


/**
 * 申请权限
 * @receiver Activity
 * @param permissions [@kotlin.ExtensionFunctionType] Function1<ArrayList<String>, Unit> 权限列表
 * @param onGranted Function2<MutableList<String>, Boolean, Unit> 成功回调
 * @param onDenied Function2<MutableList<String>, Boolean, Unit> 失败回调
 */
fun Activity.requestPerm(
    permissions: ArrayList<String>.() -> Unit,
    onGranted: (MutableList<String>, Boolean) -> Unit,
    onDenied: (MutableList<String>, Boolean) -> Unit = { list, never -> }
) {
    val xxPermissions = XXPermissions.with(this)
    ArrayList<String>().apply(permissions).forEach {
        xxPermissions.permission(it)
    }
    xxPermissions.request(object : OnPermissionCallback {
        override fun onGranted(
            permissions: MutableList<String>,
            all: Boolean
        ) {
            onGranted.invoke(permissions, all)
        }

        override fun onDenied(
            permissions: MutableList<String>,
            never: Boolean
        ) {
            if (never) {
                toast("被永久拒绝授权，请手动授予读写权限")
                // 如果是被永久拒绝就跳转到应用权限系统设置页面
                XXPermissions.startPermissionActivity(
                    this@requestPerm,
                    permissions
                )
            } else {
                toast("获取权限失败")
            }
            onDenied.invoke(permissions, never)
        }
    })
}



/**
 * @param phoneNum 手机号码
 */
fun Context.callPhone(phoneNum: String) {
    if (phoneNum.isPhoneNum()) {
        val intent = Intent(Intent.ACTION_DIAL)
        val data = Uri.parse("tel:$phoneNum")
        intent.data = data
        startActivity(intent)
    } else {
        showToast(this, "手机号码不正确!")
    }
}

//判断是否为汉字
fun String.isHan(): Boolean {
    val pattern = Pattern.compile("^[\u4e00-\u9fa5]{0,}$")
    return pattern.matcher(this).matches()
}

//判断是否为正确的手机号
fun String.isPhoneNum(): Boolean {
    val pattern =
        Pattern.compile("^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}\$")
    return pattern.matcher(this).matches()
}
//判断是否为正确的邮箱
fun String.isEmail(): Boolean {
    val pattern =
        Pattern.compile("^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+\$")
    return pattern.matcher(this).matches()
}
//空数据返回
fun String?.pk(def: String = ""): String {
    return if (this.isNullOrEmpty()) {
        def
    } else {
        this
    }
}
// 校验身份证
fun String?.isCard(): Boolean {
    val re18 =
        "/^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]\$/"
    val pattern = Pattern.compile(re18)
    return if (this.isNullOrEmpty()) {
        false
    } else {
        pattern.matcher(this).matches()
    }
}

fun FragmentActivity.showFragment(frameLayoutId: Int, fragment: Fragment) {
    supportFragmentManager.beginTransaction()
        .add(frameLayoutId, fragment)
        .show(fragment)
        .commit()
}

fun FragmentActivity.removeFragment(fragment: Fragment) {
    supportFragmentManager.beginTransaction()
        .remove(fragment)
        .commit()
}

fun FragmentActivity.hideFragment(fragment: Fragment) {
    val transaction = supportFragmentManager.beginTransaction()
    transaction.hide(fragment).commit()
}


/**
 * 防止返回null处理
 */
fun checkBoolean(isBoolean: Boolean?): Boolean {
    return isBoolean ?: false
}

/**
 * 防止返回null处理
 */
fun checkLong(long: Long?): Long {
    return long ?: 0L
}

/**
 * 防止返回null处理
 */
fun checkDouble(double: Double?): Double {
    return double ?: 0.0
}

/**
 * 防止返回null处理
 */
fun checkInt(int: Int?): Int {
    return int ?: 0
}

